package hoodoos.flow;

import hoodoos.flow.util.CollectionUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 *
 * @author zhangyunan
 */
public class FlowRules {

  private FlowRule startFlowRule;
  private final List<FlowRule> flowRuleList;
  private final FlowRulesConfig flowRulesConfig;
  private Map<String, List<FlowRule>> relationFlowRules = new HashMap<>();
  private Map<String, List<FlowCondition>> relationFlowConditions = new HashMap<>();
  private Map<String, FlowRule> flowRuleMap;

  public FlowRules(FlowRule startFlowRule, List<FlowRule> flowRuleList, FlowRulesConfig flowRulesConfig) {
    this.startFlowRule = startFlowRule;
    this.flowRuleList = flowRuleList;
    this.flowRulesConfig = flowRulesConfig;
    postConstruct();
  }

  private void postConstruct() {
    flowRuleMap = flowRuleList.stream()
        .collect(Collectors.toMap(FlowRule::getId, flowRule -> flowRule));

    for (FlowRulesConfigLine flowRulesConfigLine : flowRulesConfig.getLineList()) {

      List<FlowRule> flowRules = relationFlowRules
          .computeIfAbsent(flowRulesConfigLine.getFrom(), (from) -> new ArrayList<>());
      flowRules.add(flowRuleMap.get(flowRulesConfigLine.getTo()));

      List<FlowCondition> flowConditions = relationFlowConditions
          .computeIfAbsent(flowRulesConfigLine.getFrom(), (from) -> new ArrayList<>());

      flowConditions.add(new FlowCondition(flowRulesConfigLine));
    }

    // 排序
    relationFlowConditions.values().forEach(Collections::sort);
  }

  public List<FlowRule> getFlowRuleList() {
    return flowRuleList;
  }

  public FlowRule getStartRule() {
    return startFlowRule;
  }

  public List<FlowRule> getNextFlowRules(FlowRule flowRule) {
    return relationFlowRules.get(flowRule.getId());
  }

  public FlowRule getNextFlowRule(FlowRule flowRule) {
    return CollectionUtil.getFirstElseNull(relationFlowRules.get(flowRule.getId()));
  }

  public List<FlowCondition> getFlowCondition(FlowRule flowRule) {
    return relationFlowConditions.get(flowRule.getId());
  }

  public FlowRule getNextFlowRule(FlowCondition flowCondition) {
    return flowRuleMap.get(flowCondition.getTo());
  }
}
